package algorthm.systemTraning.unionSearch;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import util.RandomUtil;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @className: ConsistanceLogin
 * @Description:
 * @Author: wangyifei
 * @Date: 2024/4/26 8:56
 */
public class ConsistanceLogin {
    private static Logger logger = LoggerFactory.getLogger(ConsistanceLogin.class);

    public static void main(String[] args) {
        /**
         * 找出每周连续登录超过 n （n < 8） 的用户
         * */
        List<String> row = new ArrayList<>();
        for(int i = 0 ; i < 1000 ; i++){
            int userId = RandomUtil.randIntRange(2 , 20 ,99);
            for (int j = 0; j < 30; j++) {
               row.add(String.format("%s %s %s",userId , j , RandomUtil.randIntRange(2 , 20 ,99) >= 30 ? "1" : "0"));
            }
        }
    }
    public static List<String> getMaxLoginUser(List<String> rows , int days){
        List<String> rs = new ArrayList<>();
        List<LoginInfo> loginInfos = new ArrayList<>();
        for (String row : rows) {
            String[] split = row.split("\\s+");
            String userId = split[0];
            String date = split[1];
            String isLogin = split[2];
            loginInfos.add(new LoginInfo(userId , date , isLogin));
        }
        List<LoginInfo> ordered = loginInfos.stream().sorted(new Comparator<LoginInfo>() {
            @Override
            public int compare(LoginInfo o1, LoginInfo o2) {
                if(Integer.parseInt(o1.userId) == Integer.parseInt(o2.userId)){
                    return Integer.parseInt(o1.date) - Integer.parseInt(o2.date);
                }else{
                    return Integer.parseInt(o1.userId) - Integer.parseInt(o2.userId) ;
                }
            }
        }).collect(Collectors.toList());
        Map<String , List<Integer>> userLoginInfo = new HashMap<>();
        for (LoginInfo loginInfo : ordered) {
            userLoginInfo.computeIfPresent(loginInfo.userId , (key , value)->{
                value.add(Integer.parseInt(loginInfo.isLogin));
                return value ;
            });
            userLoginInfo.computeIfAbsent(loginInfo.userId , (key) -> {
                List<Integer> list = new ArrayList<>();
                list.add(Integer.parseInt(loginInfo.isLogin));
                return list;
            });
        }
        UnionSet us = new UnionSet();
        userLoginInfo.forEach((key , value)->{
            us.parents = new int[value.size()];
            us.setElement = new int[value.size()][value.size()];
            us.setIndex = new int[value.size()];
            us.sizeSet = new int[value.size()];
            for (int i = 0; i < value.size() ; i++) {
                if(value.get(i).equals(1)){
                    us.parents[i] = i ;
                    us.sizeSet[i] = 1 ;
                    us.setIndex[i] = 1 ;
                    us.setElement[i] = new int[]{i};
                }

            }
            for(int i = 1 ; i < value.size() ; i++){
                if(value.get(i-1).equals(value.get(i)) && value.get(i).equals(1)){
                    us.union(i -1 , i);
                }
            }
            int maxNode = 0 ;
            for(int i : us.sizeSet){
                maxNode = Math.max(i , maxNode);
            }
            if(maxNode > days){
                rs.add(key);
            }
        });
        return rs ;

    }
    public static class LoginInfo{

        public String userId ;
        public String date ;
        public String isLogin ;
        public LoginInfo(String s , String d , String i){
            userId = s ;
            date = d ;
            isLogin = i ;
        }
    }
    public static class UnionSet{
        public int[] parents ;
        public int[] sizeSet ;
        public int[] help ;
        public int[][] setElement ;
        public int[] setIndex;
        public void union(int i , int j){
            int iFather = getFather(i);
            int jFather = getFather(i);
            if(iFather != jFather){
                int big = (iFather > jFather ? iFather : jFather);
                int small = (iFather <= jFather ? iFather : jFather);
                parents[small] = small ;
                for(int a = 0 ; a < setElement[small].length ; a++){
                    setElement[big][setIndex[big]++] = setElement[small][a] ;
                }
                setElement[small] = null ;
                sizeSet[big] += sizeSet[small];
                sizeSet[small] = 0 ;
            }

        }
        public int getFather(int i){
            int idx = 0 ;
            int cur = 0 ;
            while(cur != parents[cur]){
                help[idx++] = cur ;
                cur = parents[cur];
            }
            idx--;
            while(idx>=0){
                parents[help[idx]] = cur ;
                idx--;
            }
            return cur ;
        }
    }
}
